package com.hongyun.tms.infra.excel.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import com.hongyun.tms.cache.CacheManager;
import com.hongyun.tms.common.constants.DefaultCreateByConstant;
import com.hongyun.tms.common.dto.tug.TugImportDto;
import com.hongyun.tms.common.enums.BizCode;
import com.hongyun.tms.common.enums.DictTypeEnum;
import com.hongyun.tms.domain.DictItemDomain;
import com.hongyun.tms.entity.TmsMTug;
import com.hongyun.tms.exception.BusinessRuntimeException;
import com.hongyun.tms.infra.ApplicationContextUtil;
import com.hongyun.tms.service.TmsMTugService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.hongyun.tms.common.constants.CommonConstants.PORT_AREA_CODE;
import static com.hongyun.tms.common.constants.CommonConstants.PORT_AREA_NAME;

/**
 * 拖轮信息导入
 *
 * @author liPeng
 * @date 2024-09-10
 */
@Slf4j
@Component
public class TugInfoExcelListener extends DefaultExcelListener<TugImportDto> {

    @Autowired
    private CacheManager cacheManager;

    @Autowired
    private TmsMTugService tugService;

    public TugInfoExcelListener(TmsMTugService tugService) {
        this.tugService = tugService;
        this.cacheManager = ApplicationContextUtil.getBean(CacheManager.class);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("成功读取excel中【" + getRows().size() + "】条客户数据");

        //TODO 2024-09-12 liPeng 导入拖轮信息的校验
        saveTugInfo();
    }


    private void saveTugInfo() {
        // 获取所有导入数据中的 tugNo 列表
        List<String> tugNoList = new ArrayList<>();
        for (TugImportDto tug : getRows()) {
            tugNoList.add(tug.getTugNo());
        }

        // 批量查询已存在的 tugNo，避免每次查询数据库
        List<String> existingTugNos = findExistingTugNos(tugNoList);
        Set<String> existingTugNoSet = new HashSet<>(existingTugNos); // 转换为 Set 以便快速查找

        List<TmsMTug> insertList = Lists.newArrayList();

        // 遍历excel数据
        for (int rowIndex = 0; rowIndex < getRows().size(); rowIndex++) {
            TugImportDto tug = getRows().get(rowIndex);

            // 校验 tugNo 是否已经存在
            if (existingTugNoSet.contains(tug.getTugNo())) {
                // 如果 tugNo 存在，则抛出异常并指定错误的行和列
                throw new BusinessRuntimeException(BizCode.EXCEL_ERROR,
                        String.format("第%d行：拖轮编号 %s 已存在，请修改后重试", rowIndex + 1, tug.getTugNo()));
            }

            // 创建拖轮对象
            TmsMTug insertTarget = new TmsMTug()
                    .setTugName(tug.getTugName())
                    .setTugNo(tug.getTugNo())
                    .setStaus(tug.getStaus())
                    .setTugTypeCode(tug.getTugTypeCode())
                    .setPortAreaName(PORT_AREA_NAME)
                    .setRegistryPort(tug.getRegistryPort())
                    .setOperator(tug.getOperator())
                    .setOwner(tug.getOwner())
                    .setBuildDate(tug.getBuildDate())
                    .setBuildFactory(tug.getBuildFactory())
                    .setImo(tug.getImo())
                    .setCallNo(tug.getCallNo())
                    .setIdNo(tug.getIdNo())
                    .setRegNo(tug.getRegNo())
                    .setTugLength(tug.getTugLength())
                    .setTugWidth(tug.getTugWidth())
                    .setTugDepth(tug.getTugDepth())
                    .setPower(tug.getPower())
                    .setHorsepower(tug.getHorsepower())
                    .setTotalTon(tug.getTotalTon())
                    .setNetTon(tug.getNetTon())
                    .setDraftFull(tug.getDraftFull())
                    .setDraftEmpty(tug.getDraftEmpty())
                    .setPortAreaCode(PORT_AREA_CODE)
                    .setCreateBy(DefaultCreateByConstant.userId)
                    .setUpdateBy(DefaultCreateByConstant.userId)
                    .setCreateByName(DefaultCreateByConstant.userId.toString())
                    .setUpdateByName(DefaultCreateByConstant.userId.toString())
                    .setCreateTime(LocalDateTime.now())
                    .setUpdateTime(LocalDateTime.now());

            insertList.add(insertTarget);
        }

        // 字典项翻译
        List<DictItemDomain> cache = cacheManager.getDictCache();
        for (TmsMTug tug : insertList) {
            for (DictItemDomain dict : cache) {
                if (dict.getDictType().equals(DictTypeEnum.TUG_TYPE.getName()) && dict.getDictValue().equals(tug.getTugTypeCode())) {
                    tug.setTugTypeName(dict.getDictLabel());
                }
            }
        }

        // 批量保存
        List<List<TmsMTug>> partitionList = Lists.partition(insertList, getSplitThreshold());
        for (List<TmsMTug> customerList : partitionList) {
            tugService.saveBatch(customerList);
        }
    }

    private List<String> findExistingTugNos(List<String> tugNoList) {
        List<TmsMTug> tugList = tugService.list(new LambdaQueryWrapper<TmsMTug>().in(TmsMTug::getTugNo, tugNoList));
        List<String> noList = tugList.stream().map(TmsMTug::getTugNo).collect(Collectors.toList());
        return CollectionUtils.isNotEmpty(noList) ? noList : Collections.emptyList();
    }

}
